/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package manager;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.*;

/**
 *
 * @author Phạm Huy Đức
 */
public class ThreadManager {

   /**
    * @param args the command line arguments Quản lý tiến trình Lấy cấu hình tên
    * Class tiến trình
    */
   private static String currentDir;
   private static List<mThread> lstThread;
   private static int port;
   private static ServerSocket serverSocket;
   public static boolean isDestroy = false;

   public static void main(String[] args) {
      System.out.println("ThreadManager is running in: " + getCurrentDir());
      loadSetting();
      createRemoteServer();
   }

   public static void createRemoteServer() {
      //Hàm nhận thông tin điều khiển từ bên ngoài
      try {
         serverSocket = new ServerSocket(port);
         while (!isDestroy) {
            Socket server;//Tạo socket với mỗi kết nối
//         serverSocket.setSoTimeout(10000);
            server = serverSocket.accept();
            eThreadManager eT = new eThreadManager(server);
            Thread t = new Thread(eT);
            t.start();
            //Cho một quãng trễ trước khi nhận kết nối mới
            Thread.sleep(100);
         }
      } catch (Exception ex) {
         Logger.getLogger(ThreadManager.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

   public static void shutdown() {
      ThreadManager.isDestroy = true;
      System.exit(1);
   }

   public static String controlServer(String command) {
      command = "" + command.trim();
      System.out.println("Get command: " + command);
      if (command.equals("shutdown -a")) {
         for (int i = 0; i < getLstThread().size(); i++) {
            getLstThread().get(i).getBgrThread().interrupt();
            getLstThread().get(i).getBgrThread().stop();
         }
         return "shutted\n";
      } else if (command.startsWith("shutdown -i ")) {
         try {
            int i = Integer.parseInt(command.replaceAll("[^0-9]+", ""));
            System.out.println("Kill thread in : " + i);
            getLstThread().get(i).getBgrThread().interrupt();
            getLstThread().get(i).getBgrThread().stop();
            return "success\n";
         } catch (Exception ex) {
            System.out.println("Cannot kill thread in command: " + command);
            return "fail";
         }
      } else if (command.equals("thread -a")) {
         StringBuilder rtStr = new StringBuilder();
         for (int i = 0; i < getLstThread().size(); i++) {
            rtStr.append(getLstThread().get(i).outStringX()).append("\n");
         }
         return rtStr.toString();
      } else {
         return "\n";
      }
   }

   /**
    * @return the currentDir
    */
   public static String getCurrentDir() {
      //Lấy đường dẫn thực của ứng dụng
      if (currentDir == null || currentDir.equals("")) {
         Path currentRelativePath = Paths.get("");
         currentDir = currentRelativePath.toAbsolutePath().toString();
      }
      return currentDir;
   }

   public static void loadSetting() {
      try {
         //Lấy file XML cấu hình thông tin
         File manager = new File(getCurrentDir() + "/config/manager.xml");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         Document doc = dBuilder.parse(manager);
         doc.getDocumentElement().normalize();
         //Chuẩn hóa
         NodeList nodes = doc.getElementsByTagName("thread");
         //Lấy thông tin port listener
         port = Integer.parseInt(doc.getElementsByTagName("port").item(0).getTextContent());
         //Lấy thông tin Class ra và load lên
         for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            mThread nodeThread = new mThread();
            if (node.getNodeType() == Node.ELEMENT_NODE) {
               Element element = (Element) node;
               nodeThread.setIndex(getValue("index", element));
               nodeThread.setStrTitle(getValue("title", element));
               nodeThread.setStrClass(getValue("class", element));
               nodeThread.setStrStartupState(getValue("startupState", element));
               nodeThread.setStrLogFile(getValue("logFile", element));
               //Thêm vào danh sách tiến trình
               //In thông tin tiến trình lấy được ra console
               System.out.println("+========================================================================================+");
               System.out.println("+ Title: \t\t" + getValue("title", element));
               System.out.println("+ Index: \t\t" + getValue("index", element));
               System.out.println("+ Class: \t\t" + getValue("class", element));
               System.out.println("+ Startup type: \t" + getValue("startupState", element));
               //Khởi tạo các tiến trình con
               Class cls = Class.forName(nodeThread.getStrClass());
               Thread obj = new Thread((Runnable) cls.newInstance());//Invoke class và chạy
               nodeThread.setBgrThread(obj);
               //Nếu kiểu khởi chạy là 1- Tự động
               if (nodeThread.getStrStartupState() != null && nodeThread.getStrStartupState().equals("1")) {
                  nodeThread.getBgrThread().start();
//                  obj.interrupt();
               } else if (nodeThread.getStrStartupState() != null && nodeThread.getStrStartupState().equals("0")) {
               }
               System.out.println("+ Log file:\t\t" + getCurrentDir() + getValue("logFile", element));
               getLstThread().add(nodeThread.clone());
            }
         }
         System.out.println("+========================================================================================+");
      } catch (Exception ex) {
         Logger.getLogger(ThreadManager.class.getName()).log(Level.SEVERE, null, ex);
      }
   }

   private static String getValue(String tag, Element element) {//Lấy giá trị
      NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
      Node node = (Node) nodes.item(0);
      return node.getNodeValue().trim();
   }

   private static Node getNode(String tag, Element element) {//Lấy node
      NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
      Node node = (Node) nodes.item(0);
      return node;
   }

   /**
    * @return the lstThread
    */
   public static List<mThread> getLstThread() {
      if (lstThread == null) {
         lstThread = new ArrayList();
      }
      return lstThread;
   }

   /**
    * @param aLstThread the lstThread to set
    */
   public static void setLstThread(List<mThread> aLstThread) {
      lstThread = aLstThread;
   }
}